package com.thekernel.youdaoyun.controller;

import com.alibaba.fastjson.JSONObject;
import com.hankcs.hanlp.HanLP;
import com.thekernel.youdaoyun.annotation.Log;
import com.thekernel.youdaoyun.bean.Note;
import com.thekernel.youdaoyun.bean.Star;
import com.thekernel.youdaoyun.exception.MyException;
import com.thekernel.youdaoyun.exception.impl.DataAlreadyExistsException;
import com.thekernel.youdaoyun.exception.impl.DataNotFoundException;
import com.thekernel.youdaoyun.exception.impl.SystemErrorException;
import com.thekernel.youdaoyun.mapper.StarMapper;
import com.thekernel.youdaoyun.service.NoteService;
import com.thekernel.youdaoyun.util.FileUtils;
import com.thekernel.youdaoyun.util.ResponseUtils;
import com.thekernel.youdaoyun.util.UserUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @Author TheKernel
 * @Date 2019/9/14 12:02d 下午
 * @Version 1.0
 * @Description 暴露给前端的笔记接口
 */
@Api(value = "笔记Controller")
@Controller
@RequestMapping("note")
public class NoteController {

    @Autowired
    private NoteService noteService;

    @Autowired
    private StarMapper starMapper;

    /**
     * 用于测试 /note 接口是否可用
     *
     * @return String
     */
    @ApiIgnore
    @GetMapping("hello")
    public @ResponseBody
    String index() {
        return "hello Note !!!";
    }

    /**
     * 添加笔记 API
     *
     * @param data 笔记信息
     * @return String 是否成功以及信息
     */
    @Log("note_add")
    @ApiOperation(value = "添加笔记", notes = "根据用户登录信息及输入笔记内容添加笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteTitle", value = "笔记标题", required = true, dataType = "string"),
            @ApiImplicitParam(name = "content", value = "笔记内容", required = true, dataType = "string"),
            @ApiImplicitParam(name = "noteSecret", value = "笔记密码", dataType = "string"),
            @ApiImplicitParam(name = "type", value = "笔记类型", dataType = "int"),
            @ApiImplicitParam(name = "category", value = "所属文件夹id", dataType = "int")
    })
    @PostMapping("add")
    public @ResponseBody
    String addNote(@RequestBody JSONObject data) throws MyException {
        String content = (String) data.get("content");
        Note note = data.toJavaObject(Note.class);
        note.setNoteUser(UserUtils.checkReturnUserId());
        int result = this.noteService.addNote(note, content);

        if (result == 1) {
            JSONObject returnData = new JSONObject();
            returnData.put("noteId", note.getNoteId());
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Note Add Success", returnData);
        } else if (result == 0) {
            throw new DataAlreadyExistsException();
        } else if (result == -1) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 添加文件夹 API
     *
     * @param data 文件夹
     * @return String 是否成功以及信息
     */
    @Log("folder_add")
    @ApiOperation(value = "添加文件夹", notes = "根据用户登录信息及输入文件夹内容添加文件夹")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteTitle", value = "文件夹标题", required = true, dataType = "string"),
            @ApiImplicitParam(name = "category", value = "父文件id", dataType = "int")
    })
    @PostMapping("/folder/add")
    public @ResponseBody
    String addFolder(@RequestBody JSONObject data) throws MyException {
        Note note = data.toJavaObject(Note.class);
        note.setNoteUser(UserUtils.checkReturnUserId());
        int result = this.noteService.addFolder(note);

        if (result == 1) {
            JSONObject returnData = new JSONObject();
            returnData.put("noteId", note.getNoteId());
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Folder Add Success", returnData);
        } else if (result == 0) {
            throw new DataAlreadyExistsException();
        } else if (result == -1) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 用户查看所有有效笔记
     *
     * @return 笔记列表
     * @throws MyException 非本人操作等
     */
//    @Log("query_valid_notes")
    @ApiOperation(value = "查询有效笔记", notes = "根据用户登录信息获取用户已有的有效笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "排序类型(1: 创建时间 2: 修改时间 3: 文件名称)", required = true, dataType = "int"),
    })
    @GetMapping("queryValid")
    public @ResponseBody
    String queryValidNotes(@RequestBody JSONObject data) throws MyException {
        int type = (int) data.get("type");
        long userId = UserUtils.checkReturnUserId();
        JSONObject returnData = new JSONObject();
        List<Note> notes = Arrays.asList(this.noteService.queryValidNotes(userId));
        returnData.put("data", returnPidNote(notes, true, type));
        returnData.put("num", notes.size());
        return ResponseUtils.response(ResponseUtils.SUCCESS, "Query Valid Notes Success", returnData);
    }

    /**
     * 用户查看最新笔记
     *
     * @return 笔记列表
     * @throws MyException 非本人操作等
     */
    @Log("query_newest_notes")
    @ApiOperation(value = "查询最新笔记", notes = "根据用户登录信息获取用户已有最新的有效笔记")
    @GetMapping("queryNewest")
    public @ResponseBody
    String queryNewestNotes() throws MyException {
        long userId = UserUtils.checkReturnUserId();
        JSONObject returnData = new JSONObject();
        List<Note> notes = Arrays.asList(this.noteService.queryValidNotes(userId));
        returnData.put("data", returnNote(notes, true, true));
        returnData.put("num", notes.size());
        return ResponseUtils.response(ResponseUtils.SUCCESS, "Query Newest Notes Success", returnData);
    }

    /**
     * 用户查看所有回收站中的笔记
     *
     * @return 笔记列表
     * @throws MyException 非本人操作等
     */
    @Log("query_deleted_notes")
    @ApiOperation(value = "查询回收站的笔记", notes = "根据用户登录信息获取用户放入到回收站的笔记")
    @GetMapping("queryDeleted")
    public @ResponseBody
    String queryDeletedNotes() throws MyException {
        long userId = UserUtils.checkReturnUserId();
        JSONObject returnData = new JSONObject();
        List<Note> notes = Arrays.asList(this.noteService.queryDeletedNotes(userId));
        returnData.put("data", returnNote(notes, false, true));
        returnData.put("num", notes.size());
        return ResponseUtils.response(ResponseUtils.SUCCESS, "Query Deleted Notes Success", returnData);
    }

    /**
     * 将笔记移动到回收站
     *
     * @param data 笔记 id
     * @return String 是否成功信息
     * @throws MyException 非本人操作等
     */
    @Log("delete_note")
    @ApiOperation(value = "将笔记移动到回收站", notes = "根据用户登录信息检测并将相应笔记移动到回收站")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long")
    })
    @DeleteMapping("delete")
    public @ResponseBody
    String deleteNote(@RequestBody JSONObject data) throws MyException {
        int result = this.noteService.deleteNote((int) data.get("noteId"));
        if (result == 1) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Delete Note Success", null);
        } else if (result == 0) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 用户删除回收站中的指定笔记
     *
     * @param data 笔记 id
     * @return 删除成功或失败
     * @throws MyException 非本人操作等
     */
    @Log("delete_deleted_note")
    @ApiOperation(value = "删除回收站中的笔记", notes = "根据用户信息以及笔记信息永久删除回收站中笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "int")
    })
    @DeleteMapping("deleteDeleted")
    public @ResponseBody
    String deleteDeletedNote(@RequestBody Note data) throws MyException {
        int result = this.noteService.deleteDeletedNote(data.getNoteId());
        if (result == 1) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Delete Deleted Note Success", null);
        } else if (result == 0) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 用户清空回收站
     *
     * @return 删除成功或失败
     * @throws MyException 非本人操作等
     */
    @Log("delete_all_deleted_note")
    @ApiOperation(value = "清空回收站中的笔记", notes = "根据用户信息以及笔记信息永久清空回收站中笔记")
    @DeleteMapping("deleteAllDeleted")
    public @ResponseBody
    String deleteAllDeletedNote() throws MyException {
        int result = this.noteService.deletedAllDeleted();
        if (result > 1) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Delete All Deleted Note Success", null);
        } else if (result == 0) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 恢复回收站中笔记
     *
     * @param note 笔记 id
     * @return 删除成功或失败
     * @throws MyException 非本人操作等
     */
    @Log("delete_deleted_note")
    @ApiOperation(value = "恢复回收站中的笔记", notes = "根据用户信息以及笔记信息恢复回收站中笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "int")
    })
    @PostMapping("recoverDeleted")
    public @ResponseBody
    String recoverDeletedNote(@RequestBody Note note) throws MyException {
        int result = this.noteService.recoverDeletedNote((note.getNoteId()));
        if (result == 1) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Recover Deleted Note Success", null);
        } else if (result == 0) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 全部恢复
     *
     * @return 恢复成功或失败
     * @throws MyException 非本人操作等
     */
    @Log("recover_all_deleted_note")
    @ApiOperation(value = "恢复回收站中的所有笔记", notes = "根据用户信息以及笔记信息恢复回收站中的所有笔记")
    @PostMapping("recoverAllDeleted")
    public @ResponseBody
    String recoverAllDeletedNote() throws MyException {
        int result = this.noteService.recoverAllDeleted();
        if (result > 0) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Recover All Deleted Note Success", null);
        } else if (result == 0) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }


    /**
     * 更新用户笔记
     *
     * @param data 笔记信息(更新后)
     * @return 更新成功与否
     * @throws MyException 非本人操作等
     */
    @Log("update_note_content")
    @ApiOperation(value = "更新有效笔记内容", notes = "根据用户信息以及笔记信息更新笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long"),
            @ApiImplicitParam(name = "noteTitle", value = "笔记标题", required = true, dataType = "String"),
            @ApiImplicitParam(name = "content", value = "笔记内容", required = true, dataType = "String")
    })
    @PutMapping("updateContent")
    public @ResponseBody
    String updateNoteContent(@RequestBody JSONObject data) throws MyException {
        String content = (String) data.get("content");
        Note note = data.toJavaObject(Note.class);
        this.noteService.updateNoteContent(note, content);
        return ResponseUtils.response(ResponseUtils.SUCCESS, "Update Note Content Success", null);
    }

    /**
     * 更新用户笔记
     *
     * @param note 笔记信息(更新后)
     * @return 更新成功与否
     * @throws MyException 非本人操作等
     */
    @Log("update_note_information")
    @ApiOperation(value = "更新有效笔记", notes = "根据用户信息以及笔记信息更新笔记密码等")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long")
    })
    @PutMapping("update")
    public @ResponseBody
    String updateNote(@RequestBody Note note) throws MyException {
        int result = this.noteService.updateNote(note);
        if (result == 1) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Update Note Success", null);
        } else {
            return ResponseUtils.response(ResponseUtils.FAILED, "Update Note Failed", null);
        }
    }

    /**
     * 更新用户笔记所属文件夹
     *
     * @param data 笔记信息(更新后)
     * @return 更新成功与否
     * @throws MyException 非本人操作等
     */
    @Log("update_note_information")
    @ApiOperation(value = "更新笔记所属文件夹", notes = "根据用户信息以及笔记信息更新笔记所属文件夹")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long"),
            @ApiImplicitParam(name = "pid", value = "文件夹Id", required = true, dataType = "long"),
    })
    @PutMapping("updatePid")
    public @ResponseBody
    String updateNotePid(@RequestBody JSONObject data) throws MyException {
        long noteId = (int) data.get("noteId");
        int category = (int) data.get("pid");
        Note note = new Note();
        note.setNoteId(noteId);
        note.setCategory(category);
        int result = this.noteService.updateNote(note);
        if (result == 1) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Update Note Success", null);
        } else {
            return ResponseUtils.response(ResponseUtils.FAILED, "Update Note Failed", null);
        }
    }

    /**
     * 查看指定笔记
     *
     * @param noteId 笔记 id
     * @return 笔记信息
     * @throws MyException 非本人操作等
     */
    @Log("query_note")
    @ApiOperation(value = "查询指定id的笔记", notes = "根据用户信息以及笔记id查询笔记内容")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long")
    })
    @GetMapping("query")
    public @ResponseBody
    String queryNote(int noteId) throws MyException {
        String result = this.noteService.queryNote(noteId);
        if (result != null) {
            JSONObject returnData = new JSONObject();
            returnData.put("data", result);
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Query Note Success", returnData);
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 重命名笔记
     *
     * @param note 新笔记(新笔记名)
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
    @Log("rename_note")
    @ApiOperation(value = "重命名笔记", notes = "根据用户登录信息以及笔记id, title重命名笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long"),
            @ApiImplicitParam(name = "noteTitle", value = "笔记title", required = true, dataType = "String")
    })
    @PutMapping("rename")
    public @ResponseBody
    String renameNote(@RequestBody Note note) throws MyException {
        int result = this.noteService.renameNote(note);
        if (result == 1) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Rename Note Success", null);
        } else if (result == 0) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 查找笔记
     *
     * @param keyword 搜索的关键字
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
    @Log("search_note")
    @ApiOperation(value = "搜索笔记", notes = "根据用户登录信息以及笔记关键字查找笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "keyword", value = "关键字", required = true, dataType = "string"),
    })
    @GetMapping("search")
    public @ResponseBody
    String searchNote(String keyword) throws MyException {
        JSONObject returnData = new JSONObject();
        List<Note> notes = Arrays.asList(this.noteService.searchNoteByKeyword(keyword));
        returnData.put("data", returnNote(notes, true, true));
        returnData.put("num", notes.size());
        return ResponseUtils.response(ResponseUtils.SUCCESS, "Query Notes Content Success", returnData);
    }

    @ApiOperation(value = "置顶笔记", notes = "根据用户所给笔记信息对笔记进行置顶")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "int"),
    })
    @PutMapping("stick")
    public @ResponseBody
    String setZ(@RequestBody JSONObject data) {
        int noteId = (int) data.get("noteId");
        this.noteService.addZ(noteId);
        return ResponseUtils.response(ResponseUtils.SUCCESS, "Stick Note Success", null);
    }

    /**
     * 笔记关键字抽取
     *
     * @param noteId 笔记 id
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
    @ApiOperation(value = "笔记关键字抽取", notes = "基于Hanlp的关键字抽取")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "int"),
    })
    @GetMapping("extract")
    public @ResponseBody
    String extractKeyword(int noteId) throws MyException {
        JSONObject returnData = new JSONObject();
        String content = noteService.queryNote(noteId);
        List<String> keywordList = HanLP.extractKeyword(content, 3);
        returnData.put("data", keywordList);
        returnData.put("num", keywordList.size());

        return ResponseUtils.response(ResponseUtils.SUCCESS, "Query Note Keyword Success", returnData);
    }

    /**
     * 查找指定文件夹下的笔记
     *
     * @param pid 搜索的文件夹id
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
    @Log("search_note")
    @ApiOperation(value = "指定文件夹下的笔记", notes = "根据用户登录信息以及文件夹id查找笔记")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pid", value = "文件夹id", required = true, dataType = "int"),
    })
    @GetMapping("folder/search")
    public @ResponseBody
    String searchNote(int pid) throws MyException {
        JSONObject returnData = new JSONObject();
        List<Note> notes = Arrays.asList(this.noteService.queryNoteByPid(pid));
        returnData.put("data", returnNote(notes, true, true));
        returnData.put("num", notes.size());
        return ResponseUtils.response(ResponseUtils.SUCCESS, "Query Newest Notes Success", returnData);
    }

    /**
     * 导出为word
     *
     * @param id 笔记对应id
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
    @Log("export_word")
    @ApiOperation(value = "导出word", notes = "根据用户登录信息以及所选笔记导出word")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long"),
    })
    @GetMapping("export/word/{id}")
    public void exportWord(HttpServletResponse response, HttpServletRequest request, @PathVariable(name = "id") int id) throws MyException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/ms-word");
        Note note = this.noteService.queryNoteById(id);
        String content = "<html><body>" + FileUtils.readFile(note.getNoteContent()) + "</body></html>";
        String title = note.getNoteTitle();

        byte[] buff = new byte[1024];
        OutputStream os = null;
        try {
            os = response.getOutputStream();
            byte[] b = content.getBytes(StandardCharsets.UTF_8);
            ByteArrayInputStream bais = new ByteArrayInputStream(b);
            POIFSFileSystem fs = new POIFSFileSystem();
            DirectoryEntry directory = fs.getRoot();
            directory.createDocument("WordDocument", bais);
            response.setHeader(
                    "Content-Disposition",
                    "attachment;filename=" + new String((title + ".doc").getBytes(StandardCharsets.UTF_8),
                            StandardCharsets.UTF_8)
            );
            fs.writeFilesystem(os);
            bais.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 导出为pdf
     *
     * @param id 笔记对应id
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
    @Log("export_pdf")
    @ApiOperation(value = "导出pdf", notes = "根据用户登录信息以及所选md导出pdf")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "noteId", value = "笔记id", required = true, dataType = "long"),
    })
    @GetMapping("export/pdf/{id}")
    public void exportPDF(HttpServletResponse response, @PathVariable(name = "id") int id) throws MyException, IOException {
        Note note = this.noteService.queryNoteById(id);
        String filename = note.getNoteContent();
        String command = "pandoc -f markdown -t latex --latex-engine=xelatex -o data/"
                + filename +
                ".pdf -V mainfont=\"WenQuanYi Micro Hei\" data/" + filename;

        StringBuilder returnString = new StringBuilder();
        Process pro = null;
        Runtime runTime = Runtime.getRuntime();
        if (runTime == null) {
            System.err.println("Create runtime false!");
            return;
        }
        try {
            pro = runTime.exec(command);
            if (pro.waitFor() != 0) {
                System.out.println("Runtime Error!!!");
            }
            BufferedReader input = new BufferedReader(new InputStreamReader(pro.getInputStream()));
            PrintWriter output = new PrintWriter(new OutputStreamWriter(pro.getOutputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                returnString.append(line).append("\n");
            }
            input.close();
            output.close();
            pro.destroy();
        } catch (IOException | InterruptedException ex) {
            Logger.getLogger(NoteController.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Error !!!");
        }
        System.out.println(returnString);

        String fileName = "data/" + filename + ".pdf";
        File file = new File(fileName);
        if (file.exists()) {
            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream outputStream = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    outputStream.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

    /**
     * 上传word
     *
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
    @Log("upload_note")
    @ApiOperation(value = "上传word", notes = "根据用户登录信息以及文件上传word(暂只支持.doc)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "word", value = "文件", required = true, dataType = "file"),
    })
    @PostMapping("import/word")
    public @ResponseBody
    String importWord(@RequestBody MultipartFile word) throws MyException, IOException, ParserConfigurationException, TransformerException {
        File file = File.createTempFile("tmp", null);
        word.transferTo(file);

        String content = this.noteService.importFromWord(file);
        Note note = new Note();
        note.setNoteTitle(word.getOriginalFilename());
        note.setNoteUser(UserUtils.checkReturnUserId());
        int result = this.noteService.addNote(note, content);

        if (result == 1) {
            JSONObject returnData = new JSONObject();
            returnData.put("noteId", note.getNoteId());
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Note Add Success", returnData);
        } else if (result == 0) {
            throw new DataAlreadyExistsException();
        } else if (result == -1) {
            throw new DataNotFoundException();
        } else {
            throw new SystemErrorException();
        }
    }

    /**
     * 上传文件夹
     *
     * @return String 是否成功及信息
     * @throws MyException 非本人操作等
     */
//    @Log("upload_dir")
    @ApiOperation(value = "上传文件夹", notes = "根据用户登录信息以及文件上传word(暂只支持.doc)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dir", value = "文件", required = true, dataType = "file"),
    })
    @PostMapping("import/dir")
    public @ResponseBody
    String importDir(@RequestBody MultipartFile[] dir) throws MyException, IOException, ParserConfigurationException, TransformerException {
        int result = 0;

        for (MultipartFile word : dir) {
            File file = File.createTempFile("tmp", null);
            word.transferTo(file);

            String content = this.noteService.importFromWord(file);
            Note note = new Note();
            note.setNoteTitle(word.getOriginalFilename());
            note.setNoteUser(UserUtils.checkReturnUserId());
            result += this.noteService.addNote(note, content);
        }

        if (result > 0) {
            return ResponseUtils.response(ResponseUtils.SUCCESS, "Note Add Success", null);
        } else if (result == 0) {
            throw new DataAlreadyExistsException();
        } else {
            throw new DataNotFoundException();
        }
    }

    /**
     * 上传图片
     *
     * @return String 是否成功及信息
     */
//    @Log("upload_image")
    @ApiOperation(value = "上传图片", notes = "上传图片信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "image", value = "图片", required = true, dataType = "file"),
    })
    @PostMapping("upload/image")
    public @ResponseBody
    String uploadImage(@RequestParam("images") MultipartFile[] images) {
        List<String> imageNames = new ArrayList<>();
        String prefix = "http://127.0.0.1:8008/api/v1/note/getImage/";
        for (MultipartFile image : images) {
            imageNames.add(prefix + FileUtils.uploadImage(image));
        }

        return ResponseUtils.response(0, imageNames);
    }

    @ApiOperation(value = "获取图片", notes = "根据图片地址获取图片")
    @ApiImplicitParams(
            @ApiImplicitParam(name = "imgName", value = "图片路径", dataType = "String", paramType = "url")
    )
    @GetMapping(value = "/getImage/{imgName}", produces = MediaType.IMAGE_JPEG_VALUE)
    public @ResponseBody
    byte[] getImage(@PathVariable(name = "imgName") String imgName) throws IOException {
        String filename = "image/" + imgName;
        File file = new File(filename);
        FileInputStream inputStream = new FileInputStream(file);
        byte[] bytes = new byte[inputStream.available()];
        inputStream.read(bytes, 0, inputStream.available());
        return bytes;
    }


    /**
     * 返回笔记列表的形式
     *
     * @param notes 笔记列表
     * @return 笔记列表的返回形式
     */
    private List<JSONObject> returnNote(List<Note> notes, Boolean needStar, Boolean folder) throws DataNotFoundException {
        Collections.sort(notes);
        List<JSONObject> returnData = new ArrayList<>();

        for (Note note : notes) {
            JSONObject tmp = new JSONObject();

            if (!note.getFolder()) {
                tmp.put("content", FileUtils.readFile(note.getNoteContent()));
            } else {
                continue;
            }
            if (folder) {
                tmp.put("folder", note.getFolder() ? 1 : 0);
            }
            tmp.put("noteId", note.getNoteId());
            tmp.put("noteTitle", note.getNoteTitle());
            tmp.put("createTime", note.getCreateTime());
            tmp.put("noteUser", note.getNoteUser());
            tmp.put("status", note.getStatus());
            tmp.put("type", note.getType());
            tmp.put("z", note.getZ());
            returnData.add(tmp);
        }

        if (needStar) {
            return noteAddStar(returnData, needStar, "noteId");
        } else {
            return returnData;
        }
    }

    /**
     * 返回携带 pid 的笔记
     *
     * @param notes 笔记列表
     * @return 携带 pid
     */
    private List<JSONObject> returnPidNote(List<Note> notes, Boolean needStar, int sortBy) throws DataNotFoundException {
        Collections.sort(notes);
        List<JSONObject> returnData = new ArrayList<>();

        notes.sort((o1, o2) -> {
            if (sortBy == 1) {
                return o1.getCreateTime().compareTo(o2.getCreateTime()) > 0 ? -1 : 1;
            } else if (sortBy == 2) {
                return o1.getUpdateTime().compareTo(o2.getUpdateTime()) > 0 ? -1 : 1;
            } else if (sortBy == 3) {
                return o1.getNoteTitle().compareTo(o2.getNoteTitle()) > 0 ? -1 : 1;
            }
            return 0;
        });

        for (Note note : notes) {
            JSONObject tmp = new JSONObject();

            tmp.put("id", note.getNoteId());
            tmp.put("name", note.getNoteTitle());
            tmp.put("pId", note.getCategory());
            if (!note.getFolder()) {
                tmp.put("content", FileUtils.readFile(note.getNoteContent()));
            }
            tmp.put("folder", note.getFolder() ? 1 : 0);
            returnData.add(tmp);
        }

        if (needStar) {
            return noteAddStar(returnData, true, "id");
        } else {
            return returnData;
        }
    }

    private List<JSONObject> noteAddStar(List<JSONObject> notes, Boolean needStar, String id) throws DataNotFoundException {
        List<JSONObject> returnData = new ArrayList<>();

        for (JSONObject note : notes) {
            Star star = this.starMapper.queryStarIdByNoteId((long) note.get(id));
            if (needStar) {
                if (star != null) {
                    note.put("star", 1);
                    note.put("starId", star.getStarId());
                } else {
                    note.put("star", 0);
                }
            }
            returnData.add(note);
        }

        return returnData;
    }

}
